Struct System.Span<T>
Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.
Jenisnya Span<T> adalah struct ref yang dialokasikan pada tumpukan daripada pada tumpukan terkelola. Jenis struct Ref memiliki sejumlah batasan untuk memastikan bahwa mereka tidak dapat dipromosikan ke tumpukan terkelola, termasuk bahwa mereka tidak dapat dikotak, mereka tidak dapat ditetapkan ke variabel jenis Object, dynamic
atau ke jenis antarmuka apa pun, mereka tidak dapat menjadi bidang dalam jenis referensi, dan tidak dapat digunakan di seluruh await
dan yield
batas. Selain itu, panggilan ke dua metode, Equals(Object) dan GetHashCode, melemparkan NotSupportedException.
Penting
Karena ini adalah jenis tumpukan-saja, Span<T>
tidak cocok untuk banyak skenario yang memerlukan penyimpanan referensi ke buffer pada tumpukan. Ini benar, misalnya, rutinitas yang melakukan panggilan metode asinkron. Untuk skenario tersebut, Anda dapat menggunakan pelengkap System.Memory<T> dan System.ReadOnlyMemory<T> jenis.
Untuk rentang yang mewakili struktur yang tidak dapat diubah atau baca-saja, gunakan System.ReadOnlySpan<T>.
Memori
mewakili Span<T>
wilayah memori arbitrer yang berdekatan. Instans Span<T>
sering digunakan untuk menahan elemen array atau sebagian array. Namun, tidak seperti array, Span<T>
instans dapat menunjuk ke memori terkelola, memori asli, atau memori yang dikelola pada tumpukan. Contoh berikut membuat Span<Byte>
dari array:
// Create a span over an array.
var array = new byte[100];
var arraySpan = new Span<byte>(array);
byte data = 0;
for (int ctr = 0; ctr < arraySpan.Length; ctr++)
arraySpan[ctr] = data++;
int arraySum = 0;
foreach (var value in array)
arraySum += value;
Console.WriteLine($"The sum is {arraySum}");
// Output: The sum is 4950
// Create a span over an array.
let array = Array.zeroCreate<byte> 100
let arraySpan = Span<byte> array
let mutable data = 0uy
for i = 0 to arraySpan.Length - 1 do
arraySpan[i] <- data
data <- data + 1uy
let mutable arraySum = 0
for value in array do
arraySum <- arraySum + int value
printfn $"The sum is {arraySum}"
// Output: The sum is 4950
Contoh berikut membuat Span<Byte>
dari 100 byte memori asli:
// Create a span from native memory.
var native = Marshal.AllocHGlobal(100);
Span<byte> nativeSpan;
unsafe
{
nativeSpan = new Span<byte>(native.ToPointer(), 100);
}
byte data = 0;
for (int ctr = 0; ctr < nativeSpan.Length; ctr++)
nativeSpan[ctr] = data++;
int nativeSum = 0;
foreach (var value in nativeSpan)
nativeSum += value;
Console.WriteLine($"The sum is {nativeSum}");
Marshal.FreeHGlobal(native);
// Output: The sum is 4950
// Create a span from native memory.
let native = Marshal.AllocHGlobal 100
let nativeSpan = Span<byte>(native.ToPointer(), 100)
let mutable data = 0uy
for i = 0 to nativeSpan.Length - 1 do
nativeSpan[i] <- data
data <- data + 1uy
let mutable nativeSum = 0
for value in nativeSpan do
nativeSum <- nativeSum + int value
printfn $"The sum is {nativeSum}"
Marshal.FreeHGlobal native
// Output: The sum is 4950
Contoh berikut menggunakan kata kunci stackalloc C# untuk mengalokasikan 100 byte memori pada tumpukan:
// Create a span on the stack.
byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
stackSpan[ctr] = data++;
int stackSum = 0;
foreach (var value in stackSpan)
stackSum += value;
Console.WriteLine($"The sum is {stackSum}");
// Output: The sum is 4950
// Create a span on the stack.
let mutable data = 0uy
let stackSpan =
let p = NativeInterop.NativePtr.stackalloc<byte> 100 |> NativeInterop.NativePtr.toVoidPtr
Span<byte>(p, 100)
for i = 0 to stackSpan.Length - 1 do
stackSpan[i] <- data
data <- data + 1uy
let mutable stackSum = 0
for value in stackSpan do
stackSum <- stackSum + int value
printfn $"The sum is {stackSum}"
// Output: The sum is 4950
Karena Span<T>
merupakan abstraksi atas blok memori semena-mena, metode jenis Span<T>
dan metode dengan Span<T>
parameter beroperasi pada objek apa pun Span<T>
terlepas dari jenis memori yang dienkapsulasinya. Misalnya, setiap bagian kode terpisah yang menginisialisasi rentang dan menghitung jumlah elemennya dapat diubah menjadi metode inisialisasi dan perhitungan tunggal, seperti yang diilustrasikan contoh berikut:
public static void WorkWithSpans()
{
// Create a span over an array.
var array = new byte[100];
var arraySpan = new Span<byte>(array);
InitializeSpan(arraySpan);
Console.WriteLine($"The sum is {ComputeSum(arraySpan):N0}");
// Create an array from native memory.
var native = Marshal.AllocHGlobal(100);
Span<byte> nativeSpan;
unsafe
{
nativeSpan = new Span<byte>(native.ToPointer(), 100);
}
InitializeSpan(nativeSpan);
Console.WriteLine($"The sum is {ComputeSum(nativeSpan):N0}");
Marshal.FreeHGlobal(native);
// Create a span on the stack.
Span<byte> stackSpan = stackalloc byte[100];
InitializeSpan(stackSpan);
Console.WriteLine($"The sum is {ComputeSum(stackSpan):N0}");
}
public static void InitializeSpan(Span<byte> span)
{
byte value = 0;
for (int ctr = 0; ctr < span.Length; ctr++)
span[ctr] = value++;
}
public static int ComputeSum(Span<byte> span)
{
int sum = 0;
foreach (var value in span)
sum += value;
return sum;
}
// The example displays the following output:
// The sum is 4,950
// The sum is 4,950
// The sum is 4,950
open System
open System.Runtime.InteropServices
open FSharp.NativeInterop
// Package FSharp.NativeInterop.NativePtr.stackalloc for reuse.
let inline stackalloc<'a when 'a: unmanaged> length : Span<'a> =
let voidPointer = NativePtr.stackalloc<'a> length |> NativePtr.toVoidPtr
Span<'a>(voidPointer, length)
let initializeSpan (span: Span<byte>) =
let mutable value = 0uy
for i = 0 to span.Length - 1 do
span[i] <- value
value <- value + 1uy
let computeSum (span: Span<byte>) =
let mutable sum = 0
for value in span do
sum <- sum + int value
sum
let workWithSpans () =
// Create a span over an array.
let array = Array.zeroCreate<byte> 100
let arraySpan = Span<byte> array
initializeSpan arraySpan
printfn $"The sum is {computeSum arraySpan:N0}"
// Create an array from native memory.
let native = Marshal.AllocHGlobal 100
let nativeSpan = Span<byte>(native.ToPointer(), 100)
initializeSpan nativeSpan
printfn $"The sum is {computeSum nativeSpan:N0}"
Marshal.FreeHGlobal native
// Create a span on the stack.
let stackSpan = stackalloc 100
initializeSpan stackSpan
printfn $"The sum is {computeSum stackSpan:N0}"
// The example displays the following output:
// The sum is 4,950
// The sum is 4,950
// The sum is 4,950
Larik
Ketika membungkus array, Span<T>
dapat membungkus seluruh array, seperti yang terjadi pada contoh di bagian Memori . Karena mendukung pemotongan, Span<T>
juga dapat menunjuk ke rentang yang bersebelahan dalam array.
Contoh berikut membuat iringan lima elemen tengah dari array bilangan bulat 10 elemen. Perhatikan bahwa kode menggandakan nilai setiap bilangan bulat dalam ikatan. Seperti yang ditunjukkan oleh output, perubahan yang dibuat oleh rentang tercermin dalam nilai array.
using System;
var array = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
var slice = new Span<int>(array, 2, 5);
for (int ctr = 0; ctr < slice.Length; ctr++)
slice[ctr] *= 2;
// Examine the original array values.
foreach (var value in array)
Console.Write($"{value} ");
Console.WriteLine();
// The example displays the following output:
// 2 4 12 16 20 24 28 16 18 20
module Program
open System
[<EntryPoint>]
let main _ =
let array = [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
let slice = Span<int>(array, 2, 5)
for i = 0 to slice.Length - 1 do
slice[i] <- slice[i] * 2
// Examine the original array values.
for value in array do
printf $"{value} "
printfn ""
0
// The example displays the following output:
// 2 4 12 16 20 24 28 16 18 20
Irisan
Span<T>
termasuk dua kelebihan beban Slice metode yang membentuk ikatan dari rentang saat ini yang dimulai pada indeks tertentu. Hal ini memungkinkan untuk memperlakukan data dalam Span<T>
sekumpulan gugus logis yang dapat diproses sesuai kebutuhan oleh bagian alur pemrosesan data dengan dampak performa minimal. Misalnya, karena protokol server modern sering kali berbasis teks, manipulasi string dan substring sangat penting. String Di kelas , metode utama untuk mengekstrak substring adalah Substring. Untuk alur data yang mengandalkan manipulasi string yang luas, penggunaannya menawarkan beberapa penalti performa, karena:
- Membuat string baru untuk menahan substring.
- Menyalin subset karakter dari string asli ke string baru.
Operasi alokasi dan penyalinan ini dapat dihilangkan dengan menggunakan Span<T>
atau ReadOnlySpan<T>, seperti yang ditunjukkan contoh berikut:
using System;
class Program2
{
static void Run()
{
string contentLength = "Content-Length: 132";
var length = GetContentLength(contentLength.ToCharArray());
Console.WriteLine($"Content length: {length}");
}
private static int GetContentLength(ReadOnlySpan<char> span)
{
var slice = span.Slice(16);
return int.Parse(slice);
}
}
// Output:
// Content length: 132
module Program2
open System
let getContentLength (span: ReadOnlySpan<char>) =
let slice = span.Slice 16
Int32.Parse slice
let contentLength = "Content-Length: 132"
let length = getContentLength (contentLength.ToCharArray())
printfn $"Content length: {length}"
// Output:
// Content length: 132
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk